package metadata_tab

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"unicode/utf8"

	"file_explorer/common/util"
	"file_explorer/model"
	"file_explorer/service"
	"file_explorer/service/eventbus"
	"file_explorer/view/packed_widgets"
	"file_explorer/view/store"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/samber/lo"
)

type MetadataEditForm struct {
	*packed_widgets.BaseComponent
	*widget.Form

	commonTagList []string
	//NoteBox *widget.Entry
	tagList *packed_widgets.HList
	preview *MetadataPreview

	tabCtx *store.MetadataTabContext
}

// 评分输入栏
func (form *MetadataEditForm) newScoreEditBox() fyne.CanvasObject {
	scoreBox := packed_widgets.NewNumEntry(nil, nil, nil)

	// 内容变更时更新预览
	scoreBox.OnChange = func(s string) {
		score, err := strconv.Atoi(s)
		if err != nil {
			return
		}
		for _, checkFile := range form.tabCtx.CheckFiles {
			checkFile.New.SetScore(&score)
		}
		form.preview.Refresh()
	}

	// 订阅预览列表checklist变更事件，更新聚合值
	form.preview.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		commonVal := ""
		if len(form.tabCtx.CheckFiles) > 0 {
			commonVal = "*"
			if util.CheckCommonValue(form.tabCtx.CheckFiles, func(item1, item2 *model.ModifiedFileInfo) bool {
				return item1.Old.GetScoreStr() == item2.Old.GetScoreStr()
			}) {
				commonVal = form.tabCtx.CheckFiles[0].Old.GetScoreStr()
			}
		}

		scoreBox.SetValue(commonVal)
		scoreBox.Refresh()
	})

	return scoreBox.Container
}

// 标签输入栏
func (form *MetadataEditForm) newTagInputBox() *widget.SelectEntry {
	// 提取当前目录tag列表，去重、排序
	metadata, _ := service.ReadLatestMetadata(form.tabCtx.Path)
	existTagSet := make(map[string]struct{})
	for _, data := range metadata.FilenameMap {
		for _, tag := range data.Tags {
			existTagSet[tag] = struct{}{}
		}
	}
	existTags := lo.Keys(existTagSet)
	sort.Slice(existTags, util.GetComparatorByPriority[int](
		true,
		func(i, j int) int {
			return len(existTags[j]) - len(existTags[i])
		},
		func(i, j int) int {
			return util.CmpText(existTags[i], existTags[j])
		},
	))

	inputBox := widget.NewSelectEntry(existTags)

	// 标签提交时更新tag列表和预览
	inputBox.OnSubmitted = func(tag string) {
		newTags := util.MergeLists(form.commonTagList, []string{tag})
		sort.Slice(newTags, util.GetComparatorByPriority[int](
			true,
			func(i, j int) int {
				return len(newTags[j]) - len(newTags[i])
			},
			func(i, j int) int {
				return util.CmpText(newTags[i], newTags[j])
			},
		))
		// 标签重复，不更新
		if len(newTags) == len(form.commonTagList) {
			return
		}

		// 更新tag列表
		form.commonTagList = newTags
		if form.tagList != nil {
			form.tagList.Refresh()
		}

		// 更新预览
		for _, checkFile := range form.tabCtx.CheckFiles {
			checkFile.New.SetTags(newTags)
		}
		form.preview.Refresh()
	}

	return inputBox
}

// 标签展示栏
func (form *MetadataEditForm) newTagsEditBox() fyne.CanvasObject {
	// tag展示列表
	form.tagList = packed_widgets.NewHList(
		0,
		func(index int) string {
			return form.commonTagList[index]
		},
		func() int {
			return len(form.commonTagList)
		},
	)

	// 双击tag删除
	form.tagList.OnDoubleTapped = func(col int) {
		form.commonTagList = append(form.commonTagList[:col], form.commonTagList[col+1:]...)
		form.tagList.RefreshData()
		form.preview.Refresh()
	}

	// tag输入框
	tagsBox := container.NewBorder(nil, nil, form.newTagInputBox(), nil, form.tagList.Table)

	// 订阅预览列表checklist变更事件，更新聚合值
	form.preview.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		var commonVal []string
		if len(form.tabCtx.CheckFiles) > 0 {
			commonVal = []string{"*"}
			if util.CheckCommonValue(form.tabCtx.CheckFiles, func(item1, item2 *model.ModifiedFileInfo) bool {
				return util.CheckListsEqual(item1.Old.GetTagList(), item2.Old.GetTagList())
			}) {
				commonVal = form.tabCtx.CheckFiles[0].Old.GetTagList()
			}
		}

		form.commonTagList = commonVal
		form.tagList.RefreshData()
	})

	return tagsBox
}

// 备注输入栏
func (form *MetadataEditForm) newNoteEditBox() fyne.CanvasObject {
	noteBox := widget.NewEntry()
	noteBox.Validator = func(note string) error {
		note = strings.TrimSpace(note)
		// note不超过300字符
		if utf8.RuneCountInString(note) > 300 {
			return fmt.Errorf("over length")
		}
		return nil
	}

	noteBox.MultiLine = true
	noteBox.SetMinRowsVisible(4)
	noteBox.Wrapping = fyne.TextWrapBreak //自动换行

	// 内容变更时更新预览
	noteBox.OnChanged = func(note string) {
		for _, checkFile := range form.tabCtx.CheckFiles {
			checkFile.New.SetNote(&note)
		}
		form.preview.Refresh()
	}

	// 订阅预览列表checklist变更事件，更新聚合值
	form.preview.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		commonVal := ""
		if len(form.tabCtx.CheckFiles) > 0 {
			commonVal = "*"
			if util.CheckCommonValue(form.tabCtx.CheckFiles, func(item1, item2 *model.ModifiedFileInfo) bool {
				return item1.Old.GetNote() == item2.Old.GetNote()
			}) {
				commonVal = form.tabCtx.CheckFiles[0].Old.GetNote()
			}
		}
		noteBox.SetText(commonVal)
		noteBox.Refresh()
	})

	return noteBox
}

// 链接输入栏
func (form *MetadataEditForm) newUrlEditBox() fyne.CanvasObject {
	urlBox := widget.NewEntry()

	// 内容变更时更新预览
	urlBox.OnChanged = func(url string) {
		for _, checkFile := range form.tabCtx.CheckFiles {
			checkFile.New.SetUrl(&url)
		}
		form.preview.Refresh()
	}

	// 订阅预览列表checklist变更事件，更新聚合值
	form.preview.Checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		commonVal := ""
		if len(form.tabCtx.CheckFiles) > 0 {
			commonVal = "*"
			if util.CheckCommonValue(form.tabCtx.CheckFiles, func(item1, item2 *model.ModifiedFileInfo) bool {
				return item1.Old.GetUrl() == item2.Old.GetUrl()
			}) {
				commonVal = form.tabCtx.CheckFiles[0].Old.GetUrl()
			}
		}
		urlBox.SetText(commonVal)
		urlBox.Refresh()
	})

	return urlBox
}

// 提交元数据改动
func (form *MetadataEditForm) submitMetadata() (string, error) {
	// 读取最新元数据
	metadata, _ := service.ReadLatestMetadata(form.tabCtx.Path)
	if metadata == nil {
		metadata = &model.FileMetadataMap{}
	}

	// 覆盖或新增文件元数据
	for _, fileInfo := range form.tabCtx.FileInfos {
		metadata.SetFileMetadata(fileInfo.New)
	}

	return service.CreateMetadata(form.tabCtx.Path, metadata)
}

func NewMetadataEditForm(tabCtx *store.MetadataTabContext, preview *MetadataPreview) *MetadataEditForm {
	form := &MetadataEditForm{
		Form:    &widget.Form{},
		preview: preview,
		tabCtx:  tabCtx,
	}

	// 表单Cancel：被选中元素重置成初始值
	form.Form.OnCancel = func() {
		preview.resetCheckItems()
		preview.Checklist.ProduceEvent(eventbus.EventKeyWidgetChecklistChange, nil)
		form.tagList.Refresh()
	}

	// 表单提交
	form.Form.OnSubmit = func() {
		_, err := form.submitMetadata()
		if err != nil {
			packed_widgets.NotifyError("元数据提交失败，错误：%s", err.Error())
		}
		// 关闭tab
		tabCtx.GetGlobalContext().RemoveTab(tabCtx.GetTabItem())
		// 如果目录打开则刷新
		tabCtx.GetGlobalContext().RefreshTabIfExists(tabCtx.Path)
	}

	form.Append("评分", form.newScoreEditBox())
	form.Append("标签", form.newTagsEditBox())
	form.Append("备注", form.newNoteEditBox())
	form.Append("链接", form.newUrlEditBox())

	return form
}
